/**
 * 
 */
package taskTracker.ui.lite;

import java.util.Timer;
import java.util.TimerTask;

import taskTracker.Task;
import taskTracker.TimeEntries;
import taskTracker.util.Helper;

/**
 * Handles all jobs that need to be run in background
 * @author aseldawy
 *
 */
public class Background extends Timer {
	
	/**59 seconds. We don't make an exact minute to avoid missing a minute*/
	private static final long ABOUT_MINUTE = 59 * 1000;

	/**The task that logs time in background*/
	private TimerTask logTimeTask;
	
	/**The task that shows a status alert to the user*/
	private TimerTask statusAlertTask;
	
	/**Singleton instance of this class*/
	public static final Background instance = new Background();

	/**Last task chosen by user*/
	private Task currentTask;

	/**Last comment entered by user*/
	private String comment;
	
	/**Interval of showing StatusAlert dialog*/
	private long statusAlertInterval;

	/**A reference to MainScreen that is used to send commands to it*/
	private MainScreen mainScreen;

	private long timeOfLastAction = System.currentTimeMillis();

	private Background() {
		super();
	}
	
	private TimerTask createLogTimeTask() {
		return new TimerTask() {
			private long startLogTime;
			{
				startLogTime = System.currentTimeMillis();
			}
			// Schedule time to log time
			public void run() {
				try {
					TimeEntries.getInstance().logTime(currentTask, startLogTime, logTimeTask.scheduledExecutionTime(), comment);
					startLogTime = logTimeTask.scheduledExecutionTime();
				} catch (Exception e) {
					Helper.displayError("Error in LogTimeTask", e);
				}
			}
		};
	}

	private TimerTask createStatusAlertTask() {
		return new TimerTask() {
			// Show alert dialog at specified time
			public void run() {
				try {
					// Its task may be running if the dialog was shown due to user input (not timer fire)
					statusAlertTask.cancel();
					statusAlertTask = null;
					
					mainScreen.showStatusAlert();

				} catch (Exception e) {
					Helper.displayError("Error in StatusAlertTask", e);
				}
			}
		};

	}

	/**
	 * Set current state to be logging time (true) or not logging time (false)
	 * @param logging
	 */
	public void startLogging(Task task, String comment, long alertInterval) {
		if (logTimeTask != null)
			throw new IllegalStateException("Already logging time");
		this.currentTask = task;
		this.comment = comment;
		this.logTimeTask = createLogTimeTask();
		this.schedule(logTimeTask, ABOUT_MINUTE, ABOUT_MINUTE);
		this.setStatusAlertInterval(alertInterval);
		this.timeOfLastAction = System.currentTimeMillis();
	}
	
	void stopLogging() {
		if (logTimeTask == null)
			throw new IllegalStateException("Not logging already");
		logTimeTask.cancel();
		logTimeTask = null;
		this.timeOfLastAction = System.currentTimeMillis();
	}

	public boolean isLogging() {
		return this.logTimeTask != null;
	}
	
	public void stop() {
		super.cancel();
	}

	/**
	 * Changes how often {@link StatusAlert} dialog is shown to user.
	 * @param millis
	 */
	public void setNotificationPeriod(long alertInterval) {
		if (statusAlertTask != null)
			statusAlertTask.cancel();
		this.statusAlertTask = createStatusAlertTask();
		this.schedule(statusAlertTask, alertInterval, alertInterval);
	}
	
	/**
	 * Current task that user currently logs time to
	 * @return
	 */
	public Task getCurrentTask() {
		return currentTask;
	}

	public String getComment() {
		return comment;
	}

	public long getStatusAlertInterval() {
		return statusAlertInterval;
	}

	public void setStatusAlertInterval(long statusAlertInterval) {
		this.statusAlertInterval = statusAlertInterval;
		// Set status alert to display
		if (this.statusAlertTask != null)
			this.statusAlertTask.cancel();
		this.statusAlertTask = createStatusAlertTask();
		this.schedule(statusAlertTask, getStatusAlertInterval());
	}

	public void setCurrentTask(Task currentTask) {
		this.currentTask = currentTask;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public void setMainScreen(MainScreen mainScreen) {
		this.mainScreen = mainScreen;
	}

	/**
	 * Total time spent in current state.
	 * If it is currently logging time, how much time logged in this session.
	 * If it is currently not logging time, how much time it was idle.
	 * @return
	 */
	public long getTotalTime() {
		return System.currentTimeMillis() - timeOfLastAction;
	}
}
